{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from flask import Flask, request, render_template, redirect,url_for,make_response, send_from_directory, session, Markup\n",
    "from gevent import pywsgi\n",
    "import os, time, markdown, sqlite3, math"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "app = Flask(__name__)\n",
    "app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024 * 1024 # max_size: 1Gb\n",
    "app.config['SECRET_KEY'] = os.urandom(24)\n",
    "app.config['FASSAGE_PATH'] = 'static/passages/'\n",
    "app.config['UPLOAD'] = 'static/uploads/'\n",
    "app.config['TEMP'] = 'static/temp/'\n",
    "app.config['ACCOUNT'] = 'lankning'\n",
    "app.config['PASSWORD'] = '123456'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def secure_filename(filename):\n",
    "    filename = filename.replace(' ','')\n",
    "    return filename"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 从md文件中读取intro和content信息\n",
    "def get_content(path):\n",
    "    with open(path,'r',encoding='utf-8') as f:\n",
    "        mdcontent = f.read()\n",
    "    info = mdcontent.split('---')[1].split('\\n') # 第一个元素是空的\n",
    "    info = [i for i in info if(len(str(i))!=0)] # 去除空元素\n",
    "    for element in info:\n",
    "        if 'title' in element:\n",
    "            title = element.split(': ')[1]\n",
    "        elif 'categories' in element:\n",
    "            categories = element.split(': ')[1]\n",
    "        elif 'date' in element:\n",
    "            date = element.split(': ')[1]\n",
    "            date = date.replace(' ','~')\n",
    "        elif 'thumbnail' in element:\n",
    "            thumbnail = element.split(': ')[1]\n",
    "    \n",
    "    text = ''\n",
    "    for i in mdcontent.split('---')[2:]:\n",
    "        text = text+i\n",
    "    text = text.replace('\\n\\n\\n\\n\\n','\\n\\n')\n",
    "    text = text.replace('\\n\\n\\n\\n','\\n\\n')\n",
    "    text = text.replace('\\n\\n\\n','\\n\\n')\n",
    "#     intro = text.split('<!--more-->')[0]\n",
    "#     text = text.split('<!--more-->')[1]\n",
    "#     intro = intro.replace('\\n','')\n",
    "#     text = text.replace('\\n\\n','\\n')\n",
    "    content = [title,categories,date,thumbnail,text]\n",
    "    return content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#md转html的方法 \n",
    "def md2html(path):\n",
    "    path = path.replace('+','/')\n",
    "    exts = ['markdown.extensions.extra', 'markdown.extensions.codehilite','markdown.extensions.tables','markdown.extensions.toc']\n",
    "    content = get_content(path)\n",
    "    mdcontent = '#'+content[0]+'\\n'+content[4]+'\\n\\n提交时间：'+content[2].replace('~',' ')\n",
    "    \n",
    "    html = markdown.markdown(mdcontent,extensions=exts)\n",
    "    content = Markup(html)\n",
    "    return content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将md文件中的![]()代码改为<!img src=>格式\n",
    "def regu_img(text):\n",
    "    text = text.split('![')\n",
    "    for i in range(len(text)-1):\n",
    "        img_info = text[i+1].split(')')[0]\n",
    "        text_info = ')'.join(text[i+1].split(')')[1:])\n",
    "        # print(text[i+1])\n",
    "        alt = img_info.split('](')[0]\n",
    "        url = img_info.split('](')[1]\n",
    "        img_html = '<br><img width=100%% src=\\\"%s\\\" alt=\\\"%s\\\" />'%(url,alt)\n",
    "        text[i+1] = img_html+text_info\n",
    "    return \"\".join(text)\n",
    "\n",
    "# 已知content，组装成规范的md文件格式\n",
    "def pack_md(content):# content = [title,categories,date,thumbnail,text]\n",
    "    info = '---\\n' + 'title: ' + content[0] + '\\ncategories: ' + content[1]+ '\\ndate: ' + content[2] + '\\nthumbnail: ' + content[3] + '\\n---\\n'\n",
    "    # 为了图片的比例，将![]()型的统一改为<img src=\"xxx\" />\n",
    "    content[4] = regu_img(content[4])\n",
    "    passage = info + content[4].replace('\\n\\n','\\n')\n",
    "    return passage"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "database=sqlite3.connect('database')\n",
    "cursor=database.cursor()\n",
    "cursor.execute('create table if not exists ttou(title text,categories text,url text,date text, thumbnail text)')\n",
    "cursor.execute('create table if not exists upload(filename text,path text,time text)')\n",
    "database.commit()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/', methods=['GET'])\n",
    "def index():\n",
    "    database=sqlite3.connect('database')\n",
    "    cursor=database.cursor()\n",
    "    cursor.execute('select * from ttou')\n",
    "    records = cursor.fetchall()\n",
    "    categories = []\n",
    "    for i in records:\n",
    "        if i[1] not in categories:\n",
    "            categories.append(i[1])\n",
    "    info = {\"passage_number\":len(records),\"total_pages\":math.ceil(len(records)/5)}\n",
    "    \n",
    "    page = request.args.get(\"page\")\n",
    "    if page==None or page=='1' or page=='0':\n",
    "        page = 1\n",
    "        records = records[0:5]\n",
    "    else:\n",
    "        page = int(page)\n",
    "        records = records[5*page-5:5*page]\n",
    "    info[\"current_page\"] = page\n",
    "    info[\"next_page\"] = '\\?page='+str(page+1)\n",
    "    info[\"former_page\"] = '\\?page='+str(page-1)\n",
    "    return render_template('index.html', info = info, categories=categories, records=records[::-1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/<category>/', methods=['GET'])\n",
    "def category(category):\n",
    "    database=sqlite3.connect('database')\n",
    "    cursor=database.cursor()\n",
    "    cursor.execute('select * from ttou')\n",
    "    records = cursor.fetchall()\n",
    "    passages = []\n",
    "    categories = []\n",
    "    for i in records:\n",
    "        if i[1] == category:\n",
    "            passages.append(i)\n",
    "        if i[1] not in categories:\n",
    "            categories.append(i[1])\n",
    "    \n",
    "    info = {\"passage_number\":len(records),\"total_pages\":math.ceil(len(passages)/5)}\n",
    "    \n",
    "    page = request.args.get(\"page\")\n",
    "    if page==None or page=='1' or page=='0':\n",
    "        page = 1\n",
    "        records = passages[0:5]\n",
    "    else:\n",
    "        page = int(page)\n",
    "        records = passages[5*page-5:5*page]\n",
    "    info[\"current_page\"] = page\n",
    "    info[\"next_page\"] =  '\\%s/?page=%s' % (category,str(page+1))\n",
    "    info[\"former_page\"] =  '\\%s/?page=%s' % (category,str(page-1))\n",
    "    return render_template('index.html', info = info, categories=categories, records=records[::-1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/login', methods=['GET','POST'])\n",
    "def login():\n",
    "    if request.method == 'GET':\n",
    "        return render_template('login.html')\n",
    "    elif request.method == 'POST':\n",
    "        username = request.form.get('username')\n",
    "        password = request.form.get('password')\n",
    "        session['username'] = username\n",
    "        session['password'] = password\n",
    "        if (session.get('username')==app.config['ACCOUNT']) and (session.get('password')==app.config['PASSWORD']):\n",
    "            return redirect(url_for(\"admin\"))\n",
    "        else:\n",
    "            return redirect(url_for(\"login\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/admin', methods=['GET','POST'])\n",
    "def admin():\n",
    "    if request.method == 'GET':\n",
    "        if (session.get('username')==app.config['ACCOUNT']) and (session.get('password')==app.config['PASSWORD']):\n",
    "            return render_template('admin.html')\n",
    "        else:\n",
    "            return redirect(url_for(\"login\"))\n",
    "    elif request.method == 'POST':\n",
    "        page = request.form.get('button')\n",
    "        # print(page)\n",
    "        return redirect(url_for(page))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/admin/modify', methods=['GET','POST'])\n",
    "def modify():\n",
    "    if request.method == 'GET':\n",
    "        if (session.get('username')==app.config['ACCOUNT']) and (session.get('password')==app.config['PASSWORD']):\n",
    "            database=sqlite3.connect('database')\n",
    "            cursor=database.cursor()\n",
    "            cursor.execute('select * from ttou')\n",
    "            records = cursor.fetchall()\n",
    "            return render_template('modify.html',records=records[::-1])\n",
    "        else:\n",
    "            return redirect(url_for(\"login\"))\n",
    "    elif request.method == 'POST':\n",
    "        database=sqlite3.connect('database')\n",
    "        cursor=database.cursor()\n",
    "        cursor.execute('select * from ttou')\n",
    "        records=cursor.fetchall()\n",
    "        \n",
    "        if request.files.get('file')==None and request.form.get('delete')!=None:# 不是上传文章 -> 文章删除功能\n",
    "            title = request.form.get('delete')\n",
    "            for i in records:\n",
    "                if i[0]==title:\n",
    "                    categories = i[1]\n",
    "            os.remove(os.path.join(app.config['FASSAGE_PATH'],categories,title+'.md'))\n",
    "            # print(title,categories,'deleted')\n",
    "            cursor.execute('DELETE FROM ttou WHERE title=\\\"%s\\\"' % title)\n",
    "            database.commit()\n",
    "            return redirect(url_for(\"modify\"))\n",
    "        elif request.form.get('button')!=None:# 有文章提交了\n",
    "            title = secure_filename(request.form.get('title'))\n",
    "            categories = request.form.get('categories')\n",
    "            text = request.form.get('text')\n",
    "            if request.form.get('date')=='':\n",
    "                localtime = time.strftime(\"%Y-%m-%d~%H:%M:%S\", time.localtime())\n",
    "            else:\n",
    "                localtime =  request.form.get('date')\n",
    "            thumbnail =  request.form.get('thumbnail')\n",
    "    #       print(context)\n",
    "            catepath = os.path.join(app.config['FASSAGE_PATH'],categories)\n",
    "            if not os.path.exists(catepath):#判断存放文章的文件夹是否存在\n",
    "                os.makedirs(catepath) # 若分类文件夹不存在就创建\n",
    "            content = [title,categories,localtime,thumbnail,text]\n",
    "            passage = pack_md(content)\n",
    "            with open('%s.md'% (os.path.join(catepath,title)), \"w+\",encoding='utf-8') as m:\n",
    "                m.write(passage)\n",
    "            target = categories+'+'+title\n",
    "            database=sqlite3.connect('database')\n",
    "            cursor=database.cursor()\n",
    "            cursor.execute('insert into ttou (title,categories,url,date,thumbnail) VALUES (\\\"%s\\\",\\\"%s\\\",\\\"%s\\\",\\\"%s\\\",\\\"%s\\\")' \n",
    "                           %(title,categories,target,localtime,thumbnail))\n",
    "            database.commit()\n",
    "            return redirect(url_for(\"read\",target=target))\n",
    "        else: # 上传文章功能 -> 跳转到预览\n",
    "            file = request.files.get('file')\n",
    "            filename = secure_filename(file.filename)\n",
    "            temp_path = os.path.join(app.config['TEMP'],filename)\n",
    "            file.save(temp_path)\n",
    "            content = get_content(temp_path)\n",
    "            # 1.title; 2.categories; 3.date; 4.thumbnail; 5.text area\n",
    "            os.remove(temp_path)\n",
    "            return render_template('new.html',content=content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/admin_edit/<target>', methods=['GET','POST'])\n",
    "def edit(target):\n",
    "    if request.method == 'GET':\n",
    "        if (session.get('username')==app.config['ACCOUNT']) and (session.get('password')==app.config['PASSWORD']):\n",
    "            content = get_content(os.path.join(app.config['FASSAGE_PATH'],target.replace('+','/')+'.md'))\n",
    "            return render_template('new.html',content=content)\n",
    "        else:\n",
    "            return redirect(url_for(\"login\"))\n",
    "    elif request.method == 'POST':\n",
    "        # 1. delete original file\n",
    "        os.remove(os.path.join(app.config['FASSAGE_PATH'],target.replace('+','/')+'.md'))\n",
    "        database=sqlite3.connect('database')\n",
    "        cursor=database.cursor()\n",
    "        cursor.execute('select * from ttou')\n",
    "        records=cursor.fetchall()\n",
    "        cursor.execute('DELETE FROM ttou WHERE title=\\\"%s\\\"' % target.split('+')[1])\n",
    "        database.commit()\n",
    "        # print(title,categories,'deleted')\n",
    "        \n",
    "        # 2. save figured file\n",
    "        # print(context)\n",
    "        title = secure_filename(request.form.get('title'))\n",
    "        categories = request.form.get('categories')\n",
    "        text = request.form.get('text')\n",
    "        if request.form.get('date')=='':\n",
    "            localtime = time.strftime(\"%Y-%m-%d~%H:%M:%S\", time.localtime())\n",
    "        else:\n",
    "            localtime =  request.form.get('date')\n",
    "        thumbnail =  request.form.get('thumbnail')\n",
    "#       print(context)\n",
    "        catepath = os.path.join(app.config['FASSAGE_PATH'],categories)\n",
    "        if not os.path.exists(catepath):#判断存放文章的文件夹是否存在\n",
    "            os.makedirs(catepath) # 若分类文件夹不存在就创建\n",
    "        content = [title,categories,localtime,thumbnail,text]\n",
    "        passage = pack_md(content)\n",
    "        with open('%s.md'% (os.path.join(catepath,title)), \"w+\",encoding='utf-8') as m:\n",
    "            m.write(passage)\n",
    "        target = categories+'+'+title\n",
    "        cursor.execute('insert into ttou (title,categories,url,date,thumbnail) VALUES (\\\"%s\\\",\\\"%s\\\",\\\"%s\\\",\\\"%s\\\",\\\"%s\\\")' \n",
    "                       %(title,categories,target,localtime,thumbnail))\n",
    "        database.commit()\n",
    "        return redirect(url_for(\"modify\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/admin/new', methods=['GET','POST'])\n",
    "def new():\n",
    "    if request.method == 'GET':\n",
    "        if (session.get('username')==app.config['ACCOUNT']) and (session.get('password')==app.config['PASSWORD']):\n",
    "            content = ['','','','','']\n",
    "            return render_template('new.html',content=content)\n",
    "        else:\n",
    "            return redirect(url_for(\"login\"))\n",
    "    elif request.method == 'POST':\n",
    "        title = secure_filename(request.form.get('title'))\n",
    "        categories = request.form.get('categories')\n",
    "        text = request.form.get('text')\n",
    "        if request.form.get('date')=='':\n",
    "            localtime = time.strftime(\"%Y-%m-%d~%H:%M:%S\", time.localtime())\n",
    "        else:\n",
    "            localtime =  request.form.get('date')\n",
    "        thumbnail =  request.form.get('thumbnail')\n",
    "#       print(context)\n",
    "        catepath = os.path.join(app.config['FASSAGE_PATH'],categories)\n",
    "        if not os.path.exists(catepath):#判断存放文章的文件夹是否存在\n",
    "            os.makedirs(catepath) # 若分类文件夹不存在就创建\n",
    "        content = [title,categories,localtime,thumbnail,text]\n",
    "        passage = pack_md(content)\n",
    "        with open('%s.md'% (os.path.join(catepath,title)), \"w+\",encoding='utf-8') as m:\n",
    "            m.write(passage)\n",
    "        target = categories+'+'+title\n",
    "        database=sqlite3.connect('database')\n",
    "        cursor=database.cursor()\n",
    "        cursor.execute('insert into ttou (title,categories,url,date,thumbnail) VALUES (\\\"%s\\\",\\\"%s\\\",\\\"%s\\\",\\\"%s\\\",\\\"%s\\\")' \n",
    "                       %(title,categories,target,localtime,thumbnail))\n",
    "        database.commit()\n",
    "        return redirect(url_for(\"read\",target=target))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/read/<target>', methods=['GET'])\n",
    "def read(target):\n",
    "    if target=='login':\n",
    "        return redirect(url_for(\"login\"))\n",
    "    else:\n",
    "        html = md2html('%s.md'% (os.path.join(app.config['FASSAGE_PATH'],target)))\n",
    "        database=sqlite3.connect('database')\n",
    "        cursor=database.cursor()\n",
    "        cursor.execute('select * from ttou')\n",
    "        records = cursor.fetchall()\n",
    "        categories = []\n",
    "        for i in records:\n",
    "            if i[1] not in categories:\n",
    "                categories.append(i[1])\n",
    "        return render_template('read.html',content = html, category = categories, records=records)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/admin/upload', methods=['GET','POST'])\n",
    "def upload():\n",
    "    if request.method == 'GET':\n",
    "        if (session.get('username')==app.config['ACCOUNT']) and (session.get('password')==app.config['PASSWORD']):\n",
    "            database=sqlite3.connect('database')\n",
    "            cursor=database.cursor()\n",
    "            cursor.execute('select * from upload')\n",
    "            records = cursor.fetchall()\n",
    "            return render_template('upload.html',records=records[::-1])\n",
    "        else:\n",
    "            return redirect(url_for(\"login\"))\n",
    "    elif request.method == 'POST':\n",
    "        database=sqlite3.connect('database')\n",
    "        cursor=database.cursor()\n",
    "        filename = request.form.get('delete')\n",
    "        if filename!=None: # 删除已经上传的文件\n",
    "            path = app.config['UPLOAD'] + filename\n",
    "            os.remove(path)\n",
    "            cursor.execute('DELETE FROM upload WHERE filename=\\\"%s\\\"' % filename)\n",
    "            database.commit()\n",
    "        else: # 上传文件\n",
    "            file = request.files.get('file')\n",
    "            filename = secure_filename(file.filename)\n",
    "            file.save(os.path.join(app.config['UPLOAD'],filename))\n",
    "            path = '/'+app.config['UPLOAD']+filename\n",
    "            localtime = time.strftime(\"%Y-%m-%d %H:%M:%S\", time.localtime())\n",
    "            cursor.execute('insert into upload (filename,path,time) VALUES (\\\"%s\\\",\\\"%s\\\",\\\"%s\\\")' \n",
    "                           %(filename,path,localtime))\n",
    "            database.commit()\n",
    "        return redirect(url_for(\"upload\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if __name__ == '__main__':\n",
    "    port=5000\n",
    "    server = pywsgi.WSGIServer(('0.0.0.0', port), app)\n",
    "    server.serve_forever()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
